/********************************************************/
/*	Copyright (C) 2016 Gong Li Bin		 	*/
/*	Project:	GlbRtbEng-1.0.0			*/
/*	Author:		gong_libin			*/
/*	Date:		2016_06_26			*/
/*	File:		GlbRtbArea.cpp			*/
/********************************************************/

#include "GlbRtbArea.h"

int CGlbRtbArea::GlbRtbBaseInput(void* pPara)
{
	int iMask = 0;
	GLBRRDATA_S stData;
	size_t iOffset = 0;
	xmlDoc* pstDoc = NULL;
	xmlNode* pstRoot = NULL;
	xmlNode* pstNode = NULL;
	xmlAttr* pstAttr = NULL;
	int iReturn = GLB_SUCCESS;
	GLBRRNODE_S* pstTree = NULL;
	char szAddr[GLB_BYTE32] = { 0 };
	void* pHead = m_CSet.GlbSetGetSet();

	((GLBRRINFO_S*)pHead)->m_iROffset = sizeof(GLBRRINFO_S);
	((GLBRRINFO_S*)pHead)->m_iTotal = GLB_RR_SUM * GLB_RR_SIZE;
	((GLBRRINFO_S*)pHead)->m_iPOffset = ((GLBRRINFO_S*)pHead)->m_iROffset;

	iOffset = GlbRtbAreaNode();
	pstTree = (GLBRRNODE_S*)((UCHAR*)pHead + iOffset);
	strcpy(pstTree->m_stData.m_szCoun, (char*)"0086");
	strcpy(pstTree->m_stData.m_szProv, (char*)"ffff");
	strcpy(pstTree->m_stData.m_szCity, (char*)"ffff");

	/* file */
	if (NULL != (pstDoc = xmlParseFile((char*)pPara))) {
		/* root */
		if (NULL != (pstRoot = xmlDocGetRootElement(pstDoc))) {
			/* node */
			GLB_RR_LOOP(pstRoot->children, pstNode)
			if (XML_ELEMENT_NODE == pstNode->type) {
				iMask = 0;
				memset(szAddr, '\0', GLB_BYTE32);
				memset(&stData, '\0', sizeof(GLBRRDATA_S));
				/* coun */
				strncpy(stData.m_szCoun, "0086", GLB_RR_AREA);
				GLB_RR_LOOP(pstNode->properties, pstAttr)
				if (NULL != pstAttr->children) {
					if (GLB_SUCCESS == strcmp((char*)pstAttr->name, GLB_RR_PROV)) {
						/* prov */
						strcpy(stData.m_szProv, (char*)pstAttr->children->content);
					}
					else if (GLB_SUCCESS == strcmp((char*)pstAttr->name, GLB_RR_CITY)) {
						/* city */
						strcpy(stData.m_szCity, (char*)pstAttr->children->content);
					}
					else if (GLB_SUCCESS == strcmp((char*)pstAttr->name, GLB_RR_ADDR)) {
						/* addr */
						strcpy(szAddr, (char*)pstAttr->children->content);
					}
					else if (GLB_SUCCESS == strcmp((char*)pstAttr->name, GLB_RR_MASK)) {
						/* mask */
						iMask = atoi((char*)pstAttr->children->content);
					}
					else {
						/* none */
					}
				}
				GLB_RR_LOOPEND
				GlbRtbAreaPut(&stData, szAddr, iMask);
			}
			GLB_RR_LOOPEND
		}
		else {
			GLB_ERROR("Failed to xmlDocGetRootElement\n");
			iReturn = GLB_FAILURE;
		}
		xmlCleanupParser();
		xmlFreeDoc(pstDoc);
	}
	else {
		GLB_ERROR("Failed to xmlParseFile\n");
		iReturn = GLB_FAILURE;
	}

	return iReturn;
}

size_t CGlbRtbArea::GlbRtbAreaNode()
{
	size_t iOffset = 0;
	void* pHead = m_CSet.GlbSetGetSet();

	if(((GLBRRINFO_S*)pHead)->m_iPOffset + sizeof(GLBRRNODE_S) < ((GLBRRINFO_S*)pHead)->m_iTotal) {
		iOffset = ((GLBRRINFO_S*)pHead)->m_iPOffset;
		((GLBRRINFO_S*)pHead)->m_iPOffset += sizeof(GLBRRNODE_S);
	}

	((GLBRRNODE_S*)((UCHAR*)pHead + iOffset))->m_iLeft = 0;
	((GLBRRNODE_S*)((UCHAR*)pHead + iOffset))->m_iRigth = 0;

	return iOffset;
}

int CGlbRtbArea::GlbRtbAreaPut(GLBRRDATA_S* pstData, char* pszAddr, int iMask)
{
	UINT uiIP = 0;
	int iIndex = 0;
	UINT uiMask = 0;
	UINT uiFlag = 1 << 31;
	struct in_addr stAddr;
	GLBRRNODE_S* pstTree = NULL;
	void* pHead = m_CSet.GlbSetGetSet();

	inet_aton(pszAddr, &stAddr);
	uiIP = ntohl(stAddr.s_addr);
	pstTree = (GLBRRNODE_S*)((UCHAR*)pHead + ((GLBRRINFO_S*)pHead)->m_iROffset);
	if (GLB_SUCCESS != strcmp(pszAddr, "0.0.0.0")) {
		while (iIndex < iMask) {
			uiMask = uiFlag >> iIndex;
			if (0 != (uiMask & uiIP)) {
				if (0 == pstTree->m_iRigth) {
					pstTree->m_iRigth = GlbRtbAreaNode();
				}
				pstTree = (GLBRRNODE_S*)((UCHAR*)pHead + pstTree->m_iRigth);
			}
			else {
				if (0 == pstTree->m_iLeft) {
					pstTree->m_iLeft = GlbRtbAreaNode();
				}
				pstTree = (GLBRRNODE_S*)((UCHAR*)pHead + pstTree->m_iLeft);
			}
			iIndex += 1;
		}
		memcpy(&pstTree->m_stData, pstData, sizeof(GLBRRDATA_S));
	}
	else {
		if (0 == iMask) {
			memcpy(&pstTree->m_stData, pstData, sizeof(GLBRRDATA_S));
		}
	}

	return GLB_SUCCESS;
}

void CGlbRtbArea::GlbRtbAreaGet(char* pszAddr, char* pszArea)
{
	UINT uiIP = 0;
	int iIndex = 0;
	UINT uiMask = 0;
	UINT uiFlag = 1 << 31;
	struct in_addr stAddr;
	GLBRRNODE_S* pstTree = NULL;
	void* pHead = m_CSet.GlbSetGetSet();

	inet_aton(pszAddr, &stAddr);
	uiIP = ntohl(stAddr.s_addr);
	pstTree = (GLBRRNODE_S*)((UCHAR*)pHead + ((GLBRRINFO_S*)pHead)->m_iROffset);
	sprintf(pszArea, "%s-%s-%s", pstTree->m_stData.m_szCoun, pstTree->m_stData.m_szProv, pstTree->m_stData.m_szCity);

	while (iIndex < 32) {
		uiMask = uiFlag >> iIndex;
		if (0 != (uiMask & uiIP)) {
			if (0 != pstTree->m_iRigth) {
				pstTree = (GLBRRNODE_S*)((UCHAR*)pHead + pstTree->m_iRigth);
			}
			else {
				break;
			}
			if (strlen(pstTree->m_stData.m_szCity) > 0) {
				sprintf(pszArea, "%s-%s-%s", pstTree->m_stData.m_szCoun, pstTree->m_stData.m_szProv, pstTree->m_stData.m_szCity);
			}
		}
		else {
			if (0 != pstTree->m_iLeft) {
				pstTree = (GLBRRNODE_S*)((UCHAR*)pHead + pstTree->m_iLeft);
			}
			else {
				break;
			}
			if (strlen(pstTree->m_stData.m_szCity) > 0) {
				sprintf(pszArea, "%s-%s-%s", pstTree->m_stData.m_szCoun, pstTree->m_stData.m_szProv, pstTree->m_stData.m_szCity);
			}
		}
		iIndex += 1;
	}

	return;
}
